//
//  JDRequestTask.swift
//  funcode
//
//  Created by Wan Jiading on 2017/2/7.
//  Copyright © 2017年 WanJiading. All rights reserved.
//	这个task的功能是从网络请求数据，并把数据保存到本地的一个临时文件，网络请求结束的时候，如果数据完整，则把数据缓存到指定的路径，不完整就删除

import UIKit
import AVFoundation

@objc protocol JDVideoRequestTaskDelegate: NSObjectProtocol {
	@objc optional func task(_ task: JDVideoRequestTask, _ didReceiveVideoLength:UInt, _ mimeType:String)
	@objc optional func didReceiveVideoData(_ task: JDVideoRequestTask)
	@objc optional func didFinishLoading(_ task: JDVideoRequestTask)
	@objc optional func didFailLoading(_ task: JDVideoRequestTask, _ errorCode: UInt)
}

class JDVideoRequestTask: NSObject, URLSessionDataDelegate, AVAssetResourceLoaderDelegate {
	var url: URL?
	var offset: UInt = 0
	
	var videoLength: UInt = 0
	var mimeType: String?
	
	var downloadingOffset: UInt = 0
	var once: Bool = false
	
	var isFinishLoad: Bool = false
	
	var delegate: JDVideoRequestTaskDelegate?
	
	var session: URLSession?
	var downloadDataTask: URLSessionDataTask?
	var taskArr: [URLSessionDataTask]!
	
	var fileHandle: FileHandle?
	var tempPath: String!
	
	override init() {
		super.init()
		
		session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main)
		
		taskArr = [URLSessionDataTask]()
		
		tempPath = JDPlayerUtil.tempVideoFilePath()
		
		if SharedFileManager.fileExists(atPath: tempPath) {
			do {
				try SharedFileManager.removeItem(atPath: tempPath)
				SharedFileManager.createFile(atPath: tempPath, contents: nil, attributes: nil)
			} catch {
				ExceptionLog("【失败】 删除文件失败 \(tempPath)")
			}
		} else {
			SharedFileManager.createFile(atPath: tempPath, contents: nil, attributes: nil)
		}
	}
	
	func setUrl(_ url: URL, _ offset: UInt) {
		self.url = url
		self.offset = offset
		
		// 如果建立第二次请求，先移除原来文件，再创建新的
		if self.taskArr.count >= 1 {
			do {
				if SharedFileManager.fileExists(atPath: tempPath!) {
					try SharedFileManager.removeItem(atPath: tempPath!)
				}
				SharedFileManager.createFile(atPath: tempPath!, contents: nil, attributes: nil)
			} catch {
				ExceptionLog("【失败】JDVideoRequestTask.setUrl.SharedFileManager.removeItem()")
			}
		}
		
		downloadingOffset = 0
		
		let actualURLComponents = NSURLComponents(url: url, resolvingAgainstBaseURL: false)
		if actualURLComponents != nil {
			actualURLComponents!.scheme = "http"
			
			var request = URLRequest(url: actualURLComponents!.url!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20.0)
			if offset > 0 && self.videoLength > 0 {
				
				let value = "bytes=\(offset)-\(self.videoLength-1)"
				request.addValue(value, forHTTPHeaderField: "Range")
			}
			
			self.downloadDataTask?.cancel()
			self.downloadDataTask = self.session!.dataTask(with: request)
			self.downloadDataTask!.resume()

			self.session!.finishTasksAndInvalidate()
			
		} else {
			ExceptionLog("actualURLComponents == nil    url = \(url)")
		}
	}
	
	func cancel() {
		self.session?.invalidateAndCancel()
	}
	
	
	
	// MARK: - URLSessionDataDelegate
	
	/** 第一次接到服务器响应 */
	func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
		DebugLog("第一次接到服务器响应")
		
		// 允许方法继续执行，否则后面的所有代理不会调用
		completionHandler(.allow)
		
		self.isFinishLoad = false
		
		self.videoLength = UInt(response.expectedContentLength)
		self.mimeType = response.mimeType!
		self.mimeType = "audio/mp3"
		
		if self.delegate != nil && self.delegate!.responds(to: #selector(JDVideoRequestTaskDelegate.task(_:_:_:))) {
			self.delegate!.task!(self, self.videoLength, self.mimeType!)
		}
		
		self.taskArr.append(downloadDataTask!)
		
		self.fileHandle = FileHandle(forWritingAtPath: tempPath)
		
	}
	
	/** 收到部分下载续传数据 */
	func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
		self.fileHandle!.seekToEndOfFile()
		
		self.fileHandle!.write(data)
		
		self.downloadingOffset = self.downloadingOffset + UInt(data.count)
		
		if self.delegate != nil && self.delegate!.responds(to: #selector(JDVideoRequestTaskDelegate.didReceiveVideoData(_:))) {
			self.delegate!.didReceiveVideoData!(self)
		}
	}
	
	@available(iOS 9.0, *)
	func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didBecome streamTask: URLSessionStreamTask) {
		DebugLog("(streamTask)")
	}
	
	/** 告诉delegate, data task 已经转变成download task. */
	func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didBecome downloadTask: URLSessionDownloadTask) {
		DebugLog("(downloadTask)")
		
	}
	
	func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void) {
		
		DebugLog("(willCacheResponse proposedResponse)")
	}
	
	/** 告诉delegate, task已经完成. */
	func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
		if error == nil {
			DebugLog("下载完成")
			if self.taskArr.count < 2 {
				self.isFinishLoad = true
				
			}
			
			if self.delegate != nil && self.delegate!.responds(to: #selector(JDVideoRequestTaskDelegate.didFinishLoading(_:))) {
				self.delegate!.didFinishLoading!(self)
			}
		} else {
			ErrorLog(error)
		}
	}
	
	/// 保存文件
	public func saveFile(_ path: String) {
		do {
			try SharedFileManager.moveItem(atPath: tempPath, toPath: path)
			DebugLog("文件拷贝到目标地址")
		} catch {
			ExceptionLog("copy 文件出错")
		}
	}
	
	
	func continueLoading() {
		once = true
		
		var actualURLComponents = URLComponents(url: self.url!, resolvingAgainstBaseURL: false)
		if actualURLComponents != nil {
			actualURLComponents!.scheme = "http"
			var request = URLRequest(url: actualURLComponents!.url!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20.0)
			if offset > 0 && self.videoLength > 0 {
				
				let value = "bytes=\(downloadingOffset)-\(self.videoLength-1)"
				request.addValue(value, forHTTPHeaderField: "Range")
			}
			
			self.downloadDataTask?.cancel()
			self.downloadDataTask = self.session!.dataTask(with: request)
			self.downloadDataTask?.resume()

			self.session!.finishTasksAndInvalidate()
			
		} else {
            ExceptionLog("actualURLComponents == nil    url = \(String(describing: url))")
		}
	}
	
	func clearData() {
		self.session?.invalidateAndCancel()
		if tempPath != nil {
			do {
				try SharedFileManager.removeItem(atPath: tempPath!)
			} catch {
				tempPath = nil
				ExceptionLog("【失败】删除 \(tempPath)")
			}
		}
	}
	
}
